package com.jiwei.community.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiwei.community.constants.SystemConstant;
import com.jiwei.community.dao.CommunityRewardMapper;
import com.jiwei.community.dao.UserCommunityLevelMapper;
import com.jiwei.community.dto.CommunityRewardDto;
import com.jiwei.community.entity.*;
import com.jiwei.community.service.CommunityRewardService;
import com.jiwei.community.service.SignInRewardService;
import com.jiwei.community.service.UserCommunityLevelService;
import com.jiwei.community.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * (CommunityReward)表服务实现类
 *
 * @author jiwei
 * @since 2024-03-21 14:50:16
 */
@Service("communityRewardService")
public class CommunityRewardServiceImpl extends ServiceImpl<CommunityRewardMapper, CommunityReward> implements CommunityRewardService {

    @Autowired
    SignInRewardService signInRewardService;
    @Autowired
    CommunityRewardMapper communityRewardMapper;
    @Autowired
    UserCommunityLevelService userCommunityLevelService;
    @Autowired
    UserService userService;
    @Override
    public void sendReward(Long userId, Long communityId, Integer duration) {
        if (userId == null){
            return;
        }
        List<CommunityRewardDto> communityRewardDtoList = communityRewardMapper.getCommunityRewardByCommunityId(communityId);
        communityRewardDtoList.stream().peek(communityRewardDto -> {
            Integer rule = communityRewardDto.getSignInReward().getRule();
            if (rule.equals(duration)){
                sendRewardWithDiffType(userId,communityRewardDto.getCommunity(),communityRewardDto.getSignInReward());
            }
        }).collect(Collectors.toList());
    }

    /**
     * 根据不同奖励配置类型执行不同的发放奖励操作
     * @param userId 发放用户id
     * @param reward 签到奖励配置
     * @param community 签到的社区
     */
    public void sendRewardWithDiffType(Long userId, Community community, SignInReward reward){

        switch (reward.getType()){
            case SystemConstant.SIGN_IN_REWARD_TYPE_EXP:
                Long expReward = Long.parseLong(reward.getVal());
                sendExpReward(userId,community.getId(),expReward);
                break;
            case SystemConstant.SIGN_IN_REWARD_TYPE_INTEGRAL:
                Integer integralReward = Integer.parseInt(reward.getVal());
                sendIntegralReward(userId,integralReward);
                break;
            default:
                break;
        }
    }

    /**
     * 发放经验者奖励
     * 主要流程为先查询社区成员表，获取指定成员的当前经验值和最高经验值，将当前经验值加上奖励经验值得到增加经验后的经验值，
     * 然后将新经验值与最大经验值进行比较若大于最大经验值，则修改用户等级+1，并用当前经验值减去最大经验值得到升级后的剩余经验值，
     * 同时修改最大经验值为新的最大经验值（新最大经验值=MaxExp+递增系数*level*递增基值）
     * @param userId 用户id
     * @param communityId 社区id
     */
    @Override
    public void sendExpReward(Long userId,Long communityId,Long expReward){
        LambdaQueryWrapper<UserCommunityLevel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCommunityLevel::getUserId,userId);
        queryWrapper.eq(UserCommunityLevel::getCommunityId,communityId);
        UserCommunityLevel level = userCommunityLevelService.getOne(queryWrapper);
        Long currExp = level.getCurrExp();
        Long maxExp = level.getMaxExp();
        currExp += expReward;
        if (maxExp!=null && currExp >= maxExp){//升级
            level.setLevel(level.getLevel()+1);
            level.setCurrExp(currExp-maxExp);
            level.setMaxExp(maxExp+SystemConstant.MAX_EXP_INCREASE_FACTOR*SystemConstant.MAX_EXP_INCREASE_BASE_VAL*level.getLevel());
        }else {//添加当前经验
            level.setCurrExp(currExp);
        }
        userCommunityLevelService.updateById(level);
    }
    @Override
    public void sendIntegralReward(Long userId,Integer integral){
        User user = userService.getById(userId);
        user.setIntegral(user.getIntegral()+integral);
        userService.updateById(user);
    }
}

